package com.bocai.user.api;

import com.bocai.CacheKey;
import com.bocai.Response;
import com.bocai.config.RedisAdapter;
import com.bocai.aspect.LoginChecker;
import com.bocai.user.model.entity.CodepayRecord;
import com.bocai.user.service.UserService;
import com.bocai.utils.JsonUtils;
import org.apache.log4j.LogManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author create by VIC.Huang
 * @date 2018/1/29
 */
@RestController
@RequestMapping("/pay")
public class PayApi {
    @Value("${codepay.token}")
    private String payToken;
    @Value("${codepay.codepayid}")
    private String codePayId;
    @Value("${codepay.key}")
    private String key;

    @Autowired
    private UserService userService;
    @Autowired
    private RedisAdapter redisAdapter;

    /**
     * 充值
     * @throws IOException
     */
    @GetMapping("/recharge")
    @LoginChecker
    public Response recharge(@RequestHeader("token")String token, @RequestParam(value = "customParam", required = false)String customParam,
                             @RequestParam("price")BigDecimal price, @RequestParam("type")String type,
                             @RequestParam("returnUrl") String returnUrl) throws IOException {
        return  new Response("http://codepay.fateqq.com:52888/creat_order?id=" + codePayId +
                "&pay_id=" + redisAdapter.get(CacheKey.TOKEN_PREFIX + token) + "&price=" + price + "&type=" + type +
                "&token=" + payToken + "&param=" + customParam + "&notify_url=&return_url=" + returnUrl);
    }

    /**
     * 支付回调方法
     */
    @PostMapping("/callback")
    public void callback(HttpServletRequest request, HttpServletResponse response) throws NoSuchAlgorithmException, IOException {
        Map<String, String> params = new HashMap<>(); //申明hashMap变量储存接收到的参数名用于排序
        Map requestParams = request.getParameterMap(); //获取请求的全部参数
        String valueStr; //申明字符变量 保存接收到的变量
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            valueStr = values[0];
            //乱码解决，这段代码在出现乱码时使用。如果sign不相等也可以使用这段代码转化
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);//增加到params保存
        }
        List<String> keys = new ArrayList<>(params.keySet()); //转为数组
        Collections.sort(keys); //重新排序
        String prestr = "";
        String sign = params.get("sign"); //获取接收到的sign 参数

        for (int i = 0; i < keys.size(); i++) { //遍历拼接url 拼接成a=1&b=2 进行MD5签名
            String key_name = keys.get(i);
            String value = params.get(key_name);
            if (value == null || value.equals("") || key_name.equals("sign")) { //跳过这些 不签名
                continue;
            }
            if (prestr.equals("")) {
                prestr = key_name + "=" + value;
            } else {
                prestr = prestr + "&" + key_name + "=" + value;
            }
        }
        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update((prestr + key).getBytes());
        String mySign = new BigInteger(1, md.digest()).toString(16).toLowerCase();
        if (mySign.length() != 32) {
            mySign = "0" + mySign;
        }

        PrintWriter out = response.getWriter();
        if (mySign.equals(sign)) {
            //编码要匹配 编码不一致中文会导致加密结果不一致
            //参数合法处理业务

            //-- 保存 支付接口返回参数
            String jsonParam = JsonUtils.toJson(params);
            CodepayRecord codepayRecord = JsonUtils.fromJson(jsonParam, CodepayRecord.class);
            userService.savePayRecord(codepayRecord);
            LogManager.getLogger(PayApi.class).info("finish!!!");
            out.print("ok");
        } else {
            //参数不合法
            LogManager.getLogger(PayApi.class).info("fail!");
            out.print("fail");
        }
    }
}
